/*
 * Copyright (C) 2021 XRADIO TECHNOLOGY CO., LTD. All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions
 *  are met:
 *    1. Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *    2. Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the
 *       distribution.
 *    3. Neither the name of XRADIO TECHNOLOGY CO., LTD. nor the names of
 *       its contributors may be used to endorse or promote products derived
 *       from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include <stdio.h>
#include <string.h>
#include "os.h"
#include "iot_gpio.h"
#include "iot_errno.h"
#include "common/cmd/cmd.h"
#include "cmd_hm.h"

/*
 * harmony iot gpio init <gpio> [m=<mode>]
 * eg.  harmony iot gpio init id=1
 */
static enum cmd_status cmd_gpio_init_exec(char *cmd)
{
    int32_t cnt;
    uint32_t id;

    cnt = cmd_sscanf(cmd, "id=%d", &id);
    if (cnt != 1) {
        HMCMD_ERR("cnt=%d,param err!!!", cnt);
        return CMD_STATUS_INVALID_ARG;
    }
    if (IoTGpioInit(id) == IOT_SUCCESS) {
        return CMD_STATUS_OK;
    }
}

/*
 * drv gpio deconfig <gpio> [m=<mode>]
 * eg. drv gpio deconfig pa6
 * eg. drv gpio deconfig pa6 m=6
 */
static enum cmd_status cmd_gpio_deinit_exec(char *cmd)
{
    int32_t cnt;
    uint32_t id;

    cnt = cmd_sscanf(cmd, "id=%d", &id);
    if (cnt != 1) {
        if (cnt != 1) {
            HMCMD_ERR("err cmd:%s,\n", cmd);
            return CMD_STATUS_INVALID_ARG;
        }
    }
    if (IoTGpioDeinit(id) == IOT_SUCCESS)
        return CMD_STATUS_OK;
    else
        return CMD_STATUS_INVALID_ARG;
}

static enum cmd_status cmd_setdir_exec(char *cmd)
{
    int32_t cnt, id;
    char direction[8];
    IotGpioDir val;

    cnt = cmd_sscanf(cmd, "id=%d dir=%7s", &id, direction);
    if (cnt != 2) {
        HMCMD_ERR("err cmd:%s\n", cmd);
        return CMD_STATUS_INVALID_ARG;
    }
    if (cmd_strcmp(direction, "input") == 0) {
        val = IOT_GPIO_DIR_IN;
    } else if (cmd_strcmp(direction, "output") == 0) {
        val = IOT_GPIO_DIR_OUT;
    } else {
        return CMD_STATUS_INVALID_ARG;
    }

    return (IoTGpioSetDir(id, val) == IOT_SUCCESS) ? CMD_STATUS_OK :
                                   CMD_STATUS_FAIL;
}

static enum cmd_status cmd_getdir_exec(char *cmd)
{
    uint32_t id, cnt;
    IotGpioDir val;

    cnt = cmd_sscanf(cmd, "id=%u", &id);
    if (cnt != 1) {
        HMCMD_ERR("err cmd:%s\n", cmd);
        return CMD_STATUS_INVALID_ARG;
    }

    if (IoTGpioGetDir(id, &val) == IOT_SUCCESS) {
        HMCMD_DBG("id=%u,dir=%s\n", id,
              ((val == 0) ? "input" : "output"));
        return CMD_STATUS_OK;
    } else {
        return CMD_STATUS_FAIL;
    }
}

/*
 * drv gpio read <gpio>
 * eg. drv gpio read pa6
 */
static enum cmd_status cmd_get_input_val_exec(char *cmd)
{
    uint32_t id, cnt;
    IotGpioValue val;

    cnt = cmd_sscanf(cmd, "id=%d", &id);
    if (cnt != 1) {
        HMCMD_ERR("err cmd:%s\n", cmd);
        return CMD_STATUS_INVALID_ARG;
    }

    if (IoTGpioGetInputVal(id, &val) == IOT_SUCCESS) {
        HMCMD_DBG("id=%d,val=%d\n", id, val);
        return CMD_STATUS_OK;
    } else {
        return CMD_STATUS_FAIL;
    }
}

static enum cmd_status cmd_get_output_val_exec(char *cmd)
{
    uint32_t id, cnt;
    IotGpioValue val;

    cnt = cmd_sscanf(cmd, "id=%d", &id);
    if (cnt != 1) {
        HMCMD_ERR("err cmd:%s\n", cmd);
        return CMD_STATUS_INVALID_ARG;
    }

    if (IoTGpioGetOutputVal(id, &val) == IOT_SUCCESS) {
        HMCMD_DBG("id=%d,val=%d\n", id, val);
        return CMD_STATUS_OK;
    } else {
        return CMD_STATUS_FAIL;
    }
}

/*
 * drv gpio write <gpio> v=<value>
 * eg. drv gpio write pa6 v=0
 */
static enum cmd_status cmd_set_output_val_exec(char *cmd)
{
    uint32_t cnt, id, temp_val;
    IotGpioValue val;

    cnt = cmd_sscanf(cmd, "id=%d v=%d", &id, &temp_val);
    if (cnt != 2) {
        HMCMD_ERR("err cmd:%s\n", cmd);
        return CMD_STATUS_INVALID_ARG;
    }
    if (temp_val == 0)
        val = IOT_GPIO_VALUE0;
    else if (temp_val == 1)
        val = IOT_GPIO_VALUE1;
    else
        return CMD_STATUS_INVALID_ARG;

    return (IoTGpioSetOutputVal(id, val) == IOT_SUCCESS) ? CMD_STATUS_OK :
                                     CMD_STATUS_FAIL;
}

static void cmd_irq_func(char *arg)
{
    HMCMD_DBG("enter isr : %s", arg);
}
static enum cmd_status cmd_regisr_exec(char *cmd)
{
    uint32_t cnt, id;
    char temp_type[8];
    char temp_pol[8];
    char cmd_test_str[8];
    IotGpioIntType type;
    IotGpioIntPolarity pol;

    cnt = cmd_sscanf(cmd, "id=%d t=%7s p=%7s", &id, temp_type, temp_pol);
    if (cnt != 3) {
        HMCMD_ERR("err cmd:%s\n", cmd);
        return CMD_STATUS_INVALID_ARG;
    }
    if (cmd_strcmp(temp_type, "level") == 0) {
        type = IOT_INT_TYPE_LEVEL;
    } else if (cmd_strcmp(temp_type, "edge") == 0) {
        type = IOT_INT_TYPE_EDGE;
    } else {
        return CMD_STATUS_INVALID_ARG;
    }

    if (cmd_strcmp(temp_pol, "low") == 0) {
        pol = IOT_GPIO_EDGE_FALL_LEVEL_LOW;
    } else if (cmd_strcmp(temp_pol, "high") == 0) {
        pol = IOT_GPIO_EDGE_RISE_LEVEL_HIGH;
    } else {
        return CMD_STATUS_INVALID_ARG;
    }

    sprintf(cmd_test_str, "isr%u", id);

    return (IoTGpioRegisterIsrFunc(id, type, pol, cmd_irq_func,
                       cmd_test_str) == IOT_SUCCESS) ?
                 CMD_STATUS_OK :
                 CMD_STATUS_FAIL;
}

static enum cmd_status cmd_unregisr_exec(char *cmd)
{
    uint32_t cnt, id;

    cnt = cmd_sscanf(cmd, "id=%d", &id);
    if (cnt != 1) {
        HMCMD_ERR("err cmd:%s\n", cmd);
        return CMD_STATUS_INVALID_ARG;
    }

    if (IoTGpioUnregisterIsrFunc(id) == IOT_SUCCESS) {
        return CMD_STATUS_OK;
    } else {
        return CMD_STATUS_FAIL;
    }
}

static enum cmd_status cmd_set_isr_mask_exec(char *cmd)
{
    uint32_t cnt, id, mask;

    cnt = cmd_sscanf(cmd, "id=%d m=%d", &id, &mask);
    if (cnt != 2) {
        HMCMD_ERR("err cmd:%s\n", cmd);
        return CMD_STATUS_INVALID_ARG;
    }

    if (IoTGpioSetIsrMask(id, mask) == IOT_SUCCESS) {
        return CMD_STATUS_OK;
    } else {
        return CMD_STATUS_FAIL;
    }
}

static enum cmd_status cmd_set_isr_mode_exec(char *cmd)
{
    uint32_t cnt, id;

    cnt = cmd_sscanf(cmd, "id=%d", &id);
    if (cnt != 1) {
        HMCMD_ERR("err cmd:%s\n", cmd);
        return CMD_STATUS_INVALID_ARG;
    }

    return (IoTGpioSetIsrMode(id, 0, 0) == IOT_SUCCESS) ? CMD_STATUS_OK :
                                    CMD_STATUS_FAIL;
}

#if CMD_DESCRIBE
#define gpio_config_help_info                                                  \
    "gpio config <gpio> m=<mode> p=<pull> l=<level> [e=<event>]\n"         \
    "\t\t\teg. gpio config pa6 m=1 p=1 l=1\n"                              \
    "\t\t\teg. gpio config pa6 m=1 p=1 l=1 e=0"
#define gpio_deconfig_help_info                                                \
    "gpio deconfig <gpio> [m=<mode>]\n"                                    \
    "\t\t\teg. gpio deconfig pa6\n"                                        \
    "\t\t\teg. gpio deconfig pa6 m=6"
#define gpio_read_help_info                                                    \
    "gpio read <gpio>\n"                                                   \
    "\t\t\teg. gpio read pa6"
#define gpio_write_help_info                                                   \
    "gpio write <gpio> v=<value>\n"                                        \
    "\t\t\teg. gpio write pa6 v=0"
#endif

static enum cmd_status cmd_gpio_help_exec(char *cmd)
{
}

static const struct cmd_data g_iot_gpio_cmds[] = {
    { "init", cmd_gpio_init_exec, CMD_DESC(gpio_config_help_info) },
    { "deinit", cmd_gpio_deinit_exec, CMD_DESC(gpio_deconfig_help_info) },
    { "setdir", cmd_setdir_exec, CMD_DESC(gpio_read_help_info) },
    { "getdir", cmd_getdir_exec, CMD_DESC(gpio_write_help_info) },
    { "setoutputval", cmd_set_output_val_exec,
      CMD_DESC(gpio_write_help_info) },
    { "getoutputval", cmd_get_output_val_exec,
      CMD_DESC(gpio_write_help_info) },
    { "getinputval", cmd_get_input_val_exec,
      CMD_DESC(gpio_write_help_info) },
    { "regisr", cmd_regisr_exec, CMD_DESC(gpio_write_help_info) },
    { "unregisr", cmd_unregisr_exec, CMD_DESC(gpio_write_help_info) },
    { "setisrmask", cmd_set_isr_mask_exec, CMD_DESC(gpio_write_help_info) },
    { "setisr", cmd_set_isr_mode_exec, CMD_DESC(gpio_write_help_info) },
    { "help", cmd_gpio_help_exec, CMD_DESC(CMD_HELP_DESC) },
};

enum cmd_status cmd_hm_iot_gpio_exec(char *cmd)
{
    return cmd_exec(cmd, g_iot_gpio_cmds, cmd_nitems(g_iot_gpio_cmds));
}
